<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>学习 REDUX</h1>

    <hr />

    <div>
      <p>当前 count: <span id="text">0</span></p>
      <button onclick="inc()">inc</button>
      <button onclick="dec()">dec</button>
      <button onclick="odd()">奇数再添加一</button>
      <button onclick="async()">隔一秒再加一</button>
    </div>

    <!-- 引入 redux 类库文件 -->
    <script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>

    <script>
      // console.log(Redux)  Redux.createStore()

      // 仓库的初始 state
      const initialState = {
        count: 0,
      };

      // 创建一个 reducer 纯函数，用于 createStore
      //      与 useReducer hook 接受的 reducer 函数一样，会接收到上一次的state与一个action动作对象
      //      1. 该函数在创建仓库时，默认会触发一次
      //          state = undefined, 可以给 state 参数设置默认值，来描述仓库 state 数据的初始值
      //          action = 初始化动作，由 REDUX 生成，里面的 type 字段的值，是一个随机数。
      //      2. 该函数在后续调用 仓库的 dispatch 方法时，会再次触发
      //      3. 该函数需要根据 state 与 action 生成一份全新的 state 数据，并返回。
      //      4. 该函数返回的 数据，就是 state。也就是 仓库的 getState() 返回的值。
      function reducer(state = initialState, action) {
        console.log("reducer", state, action);

        switch (action.type) {
          case "increment":
            // state.count++ // 修改了源数据

            return {
              ...state,
              count: state.count + 1,
            };
          case "decrement":
            return {
              ...state,
              count: state.count - 1,
            };
          case "odd":
            return state.count % 2 === 0
              ? state
              : {
                  ...state,
                  count: state.count + 1,
                };
          case "async":
            setTimeout(() => {
              return {
                ...state,
                count: state.count + 1,
              };
            }, 1000);

          default:
            return state;
        }
      }

      // 创建一个仓库，使用 Redux.createStore()
      //      const store = Redux.createStore(reducer)
      //            store 是一个仓库对象，该对象中主要有如下的一些函数
      //                1. getState()     - 返回当前 仓库中的 state 数据
      //                2. dispatch(action)     - 派发一个动作，用于修改 仓库中的 state 数据
      //                3. subscribe(callback)    - 该方法，用于订阅仓库的数据变化，当仓库数据发生变化时会触发 callback 函数
      const store = Redux.createStore(reducer);
      console.log("store", store);
      console.log("store.getState()", store.getState());

      // 调用 store.subscribe() 来处理仓库数据变化之后，自动重新 render
      store.subscribe(render);

      function inc() {
        console.log("inc");
        // 修改仓库中的数据，修改仓库数据的唯一方式，就是派发一个动作
        store.dispatch({
          type: "increment",
        });

        // 调用 render() 渲染页面
        // render()
      }

      function dec() {
        console.log("dec");
        // 修改仓库中的数据，修改仓库数据的唯一方式，就是派发一个动作
        store.dispatch({
          type: "decrement",
        });

        // 调用 render() 渲染页面
        // render()
      }

      function odd() {
        // 当前 count 为奇数再加一
        const { count } = store.getState();

        // 下面这段逻辑，可以抽到 reducer 函数中去处理
        // if (count % 2 !== 0) {
        //   store.dispatch({ type: "increment" });
        // }

        store.dispatch({ type: "odd" });
      }

      function async() {
        const { count } = store.getState();

        // 下面这段逻辑，可以抽到 reducer 函数中去处理嘛？？？？ 不行，因为 reducer 是纯函数，纯函数中不能有异步的代码。
        setTimeout(() => {
          store.dispatch({ type: "increment" });
        }, 1000);

        // store.dispatch({ type: "async" });
      }

      // 渲染页面
      function render() {
        // 获取到 id = text 的元素
        const textEl = document.querySelector("#text");
        // 获取仓库中的 state 数据
        const { count } = store.getState();
        // 将 count 写入到 textEl 的 innerHTML
        textEl.innerHTML = count;
      }
    </script>
  </body>
</html>
